home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / games / IndiZone / vroom / playmode.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  24.3 KB  |  900 lines

  1. /*
  2.  * Copyright (C) 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <stdarg.h>
  20.  
  21. #include <X11/Intrinsic.h>
  22. #include <X11/StringDefs.h>
  23. #include <Xm/Xm.h>
  24. #include <Xm/Form.h>
  25. #include <Xm/Frame.h>
  26. #include <Xm/Label.h>
  27. #include <Xm/List.h>
  28. #include <Xm/MainW.h>
  29. #include <Xm/MessageB.h>
  30. #include <Xm/PushB.h>
  31. #include <Xm/RowColumn.h>
  32. #include <Xm/SelectioB.h>
  33. #include <Xm/Separator.h>
  34. #include <Xm/TextF.h>
  35. #include <Xm/ToggleB.h>
  36. #include "Row.h"
  37.  
  38. #include "vroom.h"
  39. #include "playmode.h"
  40. #include "track.h"
  41. #include "client.h"
  42. #include "ogl.h"
  43. #include "solo.h"
  44. #include "messages.h"
  45.  
  46.  
  47. /* BEGIN PROTOTYPES -S playmode.c */
  48. static void     clearPreviewCB( Widget w, XtPointer clientData,
  49.                     XtPointer callData ) ;
  50. static void     createResultsList( Widget parent, char position[] ) ;
  51. static void     createSkillSelector( Widget parent ) ;
  52. static void     enterNameCB( Widget w, int mode,
  53.                     XmPushButtonCallbackStruct *cbs ) ;
  54. static void     placeCarsForFinish( char position[] ) ;
  55. static void     setNameCB( Widget w, Widget textField, XtPointer callData ) ;
  56. static void     setSkillLevelCB( Widget w, XtPointer clientData,
  57.                     XtPointer callData ) ;
  58. /* END PROTOTYPES -S playmode.c */
  59.  
  60.  
  61. extern Car        cars[] ;
  62. extern PlayerStruct    player[] ;
  63. extern int        playMode ;
  64. extern int        self ;
  65. extern long        gameServerId ;
  66. extern long        myHostId ;
  67. extern char        *myName ;
  68. extern Widget        playModeForm ;
  69. extern Widget        localCourseForm ;
  70. extern Widget        serverCourseForm ;
  71. extern Widget        serverForm ;
  72. extern Widget        resultsForm ;
  73. extern Widget        previewForm ;
  74. extern Widget        skillForm ;
  75. extern Widget        nameForm ;
  76. extern Widget        introWindow ;
  77. extern Widget        mainWindow ;
  78.  
  79.  
  80. static float        skillLevel[5] = { 0.70f, 0.775f, 0.85f, 0.925f, 1.0f } ;
  81.  
  82. static int        nRaces ;
  83. static float        avgHumanRaceTime ;
  84.  
  85.  
  86. /*------------------------------------------------------------------------------
  87.  * Create the chooser panel for selecting a playing mode.
  88.  *----------------------------------------------------------------------------*/
  89. void
  90. createPlayModeChooser(
  91.     Widget    parent
  92.     )
  93. {
  94.     int        n ;
  95.     Arg        args[20] ;
  96.     Widget        rc ;
  97.     Widget        label ;
  98.     Widget        w ;
  99.     XmString    str ;
  100.     static char    *helpFiles[] = { "intro.help", "playmode.help", NULL } ;
  101.  
  102.     n = 0 ;
  103.     str = XmStringCreateLocalized( "Choose a play option:" ) ;
  104.     XtSetArg( args[n], XmNlabelString, str ) ; n++ ;
  105.     XtSetArg( args[n], XmNtopAttachment, XmATTACH_FORM ) ; n++ ;
  106.     XtSetArg( args[n], XmNleftAttachment, XmATTACH_FORM ) ; n++ ;
  107.     XtSetArg( args[n], XmNrightAttachment, XmATTACH_FORM ) ; n++ ;
  108.     XtSetArg( args[n], XmNbottomAttachment, XmATTACH_NONE ) ; n++ ;
  109.     XtSetArg( args[n], XmNmarginTop, 15 ) ; n++ ;
  110.     label = XtCreateManagedWidget( "label", xmLabelWidgetClass, parent,
  111.                     args, n ) ;
  112.     XmStringFree( str ) ;
  113.  
  114.     n = 0 ;
  115.     XtSetArg( args[n], XmNtopAttachment, XmATTACH_WIDGET ) ; n++ ;
  116.     XtSetArg( args[n], XmNtopWidget, label ) ; n++ ;
  117.     XtSetArg( args[n], XmNleftAttachment, XmATTACH_FORM ) ; n++ ;
  118.     XtSetArg( args[n], XmNrightAttachment, XmATTACH_FORM ) ; n++ ;
  119.     XtSetArg( args[n], XmNbottomAttachment, XmATTACH_FORM ) ; n++ ;
  120.     XtSetArg( args[n], XmNentryAlignment, XmALIGNMENT_CENTER ) ; n++ ;
  121.     XtSetArg( args[n], XmNorientation, XmVERTICAL ) ; n++ ;
  122.     XtSetArg( args[n], XmNpacking, XmPACK_TIGHT ) ; n++ ;
  123.     XtSetArg( args[n], XmNadjustLast, True ) ; n++ ;
  124.     XtSetArg( args[n], XmNspacing, 10 ) ; n++ ;
  125.     XtSetArg( args[n], XmNmarginHeight, 10 ) ; n++ ;
  126.     XtSetArg( args[n], XmNmarginWidth, 10 ) ; n++ ;
  127.     rc = XtCreateManagedWidget( "rowColumn", xmRowColumnWidgetClass, parent,
  128.                 args, n ) ;
  129.  
  130.     n = 0 ;
  131.     XtSetArg( args[n], XmNmarginTop, 5 ) ; n++ ;
  132.     XtSetArg( args[n], XmNmarginBottom, 5 ) ; n++ ;
  133.     w = addMenuPushButton( rc, "Solo", args, n, (XtCallbackProc)enterNameCB,
  134.                 (XtPointer)VROOM_SOLO ) ;
  135.     w = addMenuPushButton( rc, "Multi-player", args, n,
  136.             (XtCallbackProc)enterNameCB, (XtPointer)VROOM_TEAM ) ;
  137.     w = addMenuPushButton( rc, "Help", args, n, helpCB, helpFiles ) ;
  138.     w = addMenuPushButton( rc, "About", args, n, aboutCB, NULL ) ;
  139.     w = addMenuPushButton( rc, "Quit", args, n, exitCB, 0 ) ;
  140. }
  141.  
  142.  
  143.  
  144. /*------------------------------------------------------------------------------
  145.  * Pick the skill level for the solo game.
  146.  *----------------------------------------------------------------------------*/
  147. void
  148. pickSkillLevelCB(
  149.     Widget        w,
  150.     XtPointer    clientData,
  151.     XtPointer    callData
  152.     )
  153. {
  154.     busyCursor() ;
  155.  
  156.     createSkillSelector( skillForm ) ;
  157.  
  158.     setAdminForm( skillForm ) ;
  159.  
  160.     unbusyCursor() ;
  161. }
  162.  
  163.  
  164.  
  165. /*------------------------------------------------------------------------------
  166.  * Automatically adjust the skill level for the solo game.
  167.  *----------------------------------------------------------------------------*/
  168. void
  169. autoSkillLevelCB(
  170.     Widget        w,
  171.     XtPointer    clientData,
  172.     XtPointer    callData
  173.     )
  174. {
  175.     int    i ;
  176.     int    firstPlace = 1 ;
  177.     float    bestRobotTime = 1e30 ;
  178.     float    nextBestRobotTime = 1e30 ;
  179.     float    skill ;
  180.     float    oldSkill ;
  181.  
  182.     busyCursor() ;
  183.  
  184.     avgHumanRaceTime = ( nRaces * avgHumanRaceTime +
  185.                 cars[self].bestLapTime ) / ( nRaces + 1 ) ;
  186.     nRaces++ ;
  187.  
  188.     if( cars[self].finishTime < 99.0f * 60.0f )
  189.     {
  190.         for( i = 0 ; i  < MAX_PLAYERS ; i++ )
  191.         {
  192.             if( i != self )
  193.             {
  194.                 if( cars[i].bestLapTime < bestRobotTime )
  195.                 {
  196.                     nextBestRobotTime = bestRobotTime ;
  197.                     bestRobotTime = cars[i].bestLapTime ;
  198.                 }
  199.                 else if( cars[i].finishTime <
  200.                     nextBestRobotTime )
  201.                 {
  202.                     nextBestRobotTime = cars[i].bestLapTime;
  203.                 }
  204.                 if( cars[i].bestLapTime <
  205.                     cars[self].bestLapTime )
  206.                 {
  207.                     firstPlace = 0 ;
  208.                 }
  209.             }
  210.         }
  211.         /*
  212.          * Set this time just to get the return value.  Actuall skill
  213.          * setting is set later.
  214.          */
  215.         oldSkill = setRobotChars( 0.75f ) ;
  216.         if( nextBestRobotTime < avgHumanRaceTime )
  217.         {
  218.             skill = ( 1.0f - 0.02f * avgHumanRaceTime /
  219.                 nextBestRobotTime ) * oldSkill ;
  220.         }
  221.         else
  222.         {
  223.             skill = 0.20f * ( 1.0f - oldSkill ) *
  224.                 nextBestRobotTime / avgHumanRaceTime +
  225.                 oldSkill ;
  226.         }
  227.         skill = MINFUNC( skill, 1.0f ) ;
  228.         oldSkill = setRobotChars( skill ) ;
  229.     }
  230.  
  231.     startTimeTrials( 1 ) ;
  232.  
  233.     unbusyCursor() ;
  234. }
  235.  
  236.  
  237.  
  238. /*------------------------------------------------------------------------------
  239.  * Create the chooser panel for selecting a skill level.
  240.  *----------------------------------------------------------------------------*/
  241. static void
  242. createSkillSelector(
  243.     Widget    parent
  244.     )
  245. {
  246.     int        n ;
  247.     Arg        args[20] ;
  248.     Widget        rc ;
  249.     Widget        label ;
  250.     Widget        w ;
  251.     XmString    str ;
  252.     static char    *helpFiles[] = { "skill.help", NULL } ;
  253.     static int    init = 0 ;
  254.  
  255.     if( init == 1 )
  256.     {
  257.         return ;
  258.     }
  259.     init = 1 ;
  260.         
  261.     n = 0 ;
  262.     str = XmStringCreateLocalized( "Choose a skill level:" ) ;
  263.     XtSetArg( args[n], XmNlabelString, str ) ; n++ ;
  264.     XtSetArg( args[n], XmNtopAttachment, XmATTACH_FORM ) ; n++ ;
  265.     XtSetArg( args[n], XmNleftAttachment, XmATTACH_FORM ) ; n++ ;
  266.     XtSetArg( args[n], XmNrightAttachment, XmATTACH_FORM ) ; n++ ;
  267.     XtSetArg( args[n], XmNbottomAttachment, XmATTACH_POSITION ) ; n++ ;
  268.     XtSetArg( args[n], XmNbottomPosition, 11 ) ; n++ ;
  269.     label = XtCreateManagedWidget( "label", xmLabelWidgetClass, parent,
  270.                     args, n ) ;
  271.     XmStringFree( str ) ;
  272.  
  273.     n = 0 ;
  274.     XtSetArg( args[n], XmNtopPosition, 12 ) ; n++ ;
  275.     XtSetArg( args[n], XmNbottomPosition, 22 ) ; n++ ;
  276.     XtSetArg( args[n], XmNtopAttachment, XmATTACH_POSITION ) ; n++ ;
  277.     XtSetArg( args[n], XmNleftAttachment, XmATTACH_POSITION ) ; n++ ;
  278.     XtSetArg( args[n], XmNleftPosition, 3 ) ; n++ ;
  279.     XtSetArg( args[n], XmNrightAttachment, XmATTACH_POSITION ) ; n++ ;
  280.     XtSetArg( args[n], XmNrightPosition, 97 ) ; n++ ;
  281.     XtSetArg( args[n], XmNbottomAttachment, XmATTACH_POSITION ) ; n++ ;
  282.     w = addMenuPushButton( parent, "Easy", args, n, setSkillLevelCB,
  283.                 (XtPointer)0 ) ;
  284.  
  285.     XtSetArg( args[0], XmNtopPosition, 23 ) ;
  286.     XtSetArg( args[1], XmNbottomPosition, 33 ) ;
  287.     w = addMenuPushButton( parent, "Simple", args, n, setSkillLevelCB,
  288.                 (XtPointer)1 ) ;
  289.  
  290.     XtSetArg( args[0], XmNtopPosition, 34 ) ;
  291.     XtSetArg( args[1], XmNbottomPosition, 44 ) ;
  292.     w = addMenuPushButton( parent, "Medium", args, n, setSkillLevelCB,
  293.                 (XtPointer)2 ) ;
  294.  
  295.     XtSetArg( args[0], XmNtopPosition, 45 ) ;
  296.     XtSetArg( args[1], XmNbottomPosition, 55 ) ;
  297.     w = addMenuPushButton( parent, "Challenging", args, n, setSkillLevelCB,
  298.                 (XtPointer)3 ) ;
  299.  
  300.     XtSetArg( args[0], XmNtopPosition, 56 ) ;
  301.     XtSetArg( args[1], XmNbottomPosition, 66 ) ;
  302.     w = addMenuPushButton( parent, "Difficult", args, n, setSkillLevelCB,
  303.                 (XtPointer)4 ) ;
  304.  
  305.     XtSetArg( args[0], XmNtopPosition, 76 ) ;
  306.     XtSetArg( args[1], XmNbottomPosition, 86 ) ;
  307.     w = addMenuPushButton( parent, "Help", args, n, helpCB, helpFiles ) ;
  308.  
  309.     XtSetArg( args[0], XmNtopPosition, 87 ) ;
  310.     XtSetArg( args[1], XmNbottomPosition, 97 ) ;
  311.     w = addMenuPushButton( parent, "Quit", args, n, exitCB, 0 ) ;
  312.  
  313.     n = 0 ;
  314.     XtSetArg( args[n], XmNtopAttachment, XmATTACH_POSITION ) ; n++ ;
  315.     XtSetArg( args[n], XmNtopPosition, 67 ) ; n++ ;
  316.     XtSetArg( args[n], XmNleftAttachment, XmATTACH_FORM ) ; n++ ;
  317.     XtSetArg( args[n], XmNrightAttachment, XmATTACH_FORM ) ; n++ ;
  318.     XtSetArg( args[n], XmNbottomAttachment, XmATTACH_POSITION ) ; n++ ;
  319.     XtSetArg( args[n], XmNbottomPosition, 75 ) ; n++ ;
  320.     XtSetArg( args[n], XmNorientation, XmHORIZONTAL ) ; n++ ;
  321.     w = XtCreateManagedWidget( "separator", xmSeparatorWidgetClass,
  322.                     parent, args, n ) ;
  323. }
  324.  
  325.  
  326.  
  327. /*------------------------------------------------------------------------------
  328.  * Set the skill level.
  329.  *----------------------------------------------------------------------------*/
  330. static void
  331. setSkillLevelCB(
  332.     Widget        w,
  333.     XtPointer    clientData,
  334.     XtPointer    callData
  335.     )
  336. {
  337.     busyCursor() ;
  338.  
  339.     playMode = VROOM_SOLO ;
  340.  
  341.     setRobotChars( skillLevel[(int)clientData] ) ;
  342.  
  343.     nRaces = 0 ;
  344.     avgHumanRaceTime = 0.0f ;
  345.  
  346.     createLocalCourseSelector( localCourseForm ) ;
  347.  
  348.     setAdminForm( localCourseForm ) ;
  349.  
  350.     unbusyCursor() ;
  351. }
  352.  
  353.  
  354.  
  355. /*------------------------------------------------------------------------------
  356.  * Start team mode of game.
  357.  *----------------------------------------------------------------------------*/
  358. void
  359. startTeamModeCB(
  360.     Widget        w,
  361.     XtPointer    clientData,
  362.     XtPointer    callData
  363.     )
  364. {
  365.     playMode = VROOM_TEAM ;
  366.  
  367.     busyCursor() ;
  368.  
  369.     checkPorts() ;
  370.  
  371.     createServerSelector( serverForm ) ;
  372.  
  373.     setAdminForm( serverForm ) ;
  374.  
  375.     if( mainWindow != NULL && XtIsManaged( mainWindow ) )
  376.     {
  377.         controlMainWindow( 0 ) ;
  378.     }
  379.  
  380.     if( introWindow != NULL && !XtIsManaged( introWindow ) )
  381.     {
  382.         controlIntroWindow( 1 ) ;
  383.     }
  384.  
  385.     listenForServers() ;
  386.  
  387.     unbusyCursor() ;
  388. }
  389.  
  390.  
  391.  
  392. /*------------------------------------------------------------------------------
  393.  * End solo game, show results of last race.
  394.  *----------------------------------------------------------------------------*/
  395. void
  396. showSoloResults(
  397.     char    position[]
  398.     )
  399. {
  400.     busyCursor() ;
  401.  
  402.     createResultsList( resultsForm, position ) ;
  403.  
  404.     setAdminForm( resultsForm ) ;
  405.  
  406.     controlMainWindow( 0 ) ;
  407.  
  408.     setIntroCarShot() ;
  409.  
  410.     controlIntroWindow( 1 ) ;
  411.  
  412.     unbusyCursor() ;
  413. }
  414.  
  415.  
  416.  
  417. /*------------------------------------------------------------------------------
  418.  * End network game, show results of last race.
  419.  *----------------------------------------------------------------------------*/
  420. void
  421. showTeamResults(
  422.     char    position[]
  423.     )
  424. {
  425.     busyCursor() ;
  426.  
  427.     createResultsList( resultsForm, position ) ;
  428.  
  429.     setAdminForm( resultsForm ) ;
  430.  
  431.     controlMainWindow( 0 ) ;
  432.  
  433.     setIntroCarShot() ;
  434.  
  435.     controlIntroWindow( 1 ) ;
  436.  
  437.     unbusyCursor() ;
  438. }
  439.  
  440.  
  441.  
  442. /*------------------------------------------------------------------------------
  443.  * Create the results list.
  444.  *----------------------------------------------------------------------------*/
  445. static void
  446. createResultsList(
  447.     Widget    parent,
  448.     char    position[]
  449.     )
  450. {
  451.     int        i ;
  452.     int        n ;
  453.     int        l ;
  454.     char        line[256] ;
  455.     Arg        args[10] ;
  456.     Widget        button[4] ;
  457.     static char    *labels[4] = { "New Race", "Rematch", "Quit", "Help" } ;
  458.     XmString    str ;
  459.     static int    init = 0 ;
  460.     static Widget    raceResults ;
  461.     static Widget    resultsList ;
  462.     static char    *soloHelpFiles[] = { "soloresults.help", NULL } ;
  463.     static char    *teamHelpFiles[] = { "teamresults.help", NULL } ;
  464.  
  465.     if( init == 0 )
  466.     {
  467.         init = 1 ;
  468.  
  469.         n = 0 ;
  470.         XtSetArg( args[n], XmNtopAttachment, XmATTACH_FORM ) ; n++ ;
  471.         XtSetArg( args[n], XmNleftAttachment, XmATTACH_FORM ) ; n++ ;
  472.         XtSetArg( args[n], XmNrightAttachment, XmATTACH_FORM ) ; n++ ;
  473.         XtSetArg( args[n], XmNbottomAttachment, XmATTACH_NONE ) ; n++ ;
  474.         createSelectionList( "Race results:", parent, &resultsList,
  475.                     4, button, labels, args, n ) ;
  476.  
  477.         if( playMode == VROOM_SOLO )
  478.         {
  479.             XtAddCallback( button[0], XmNactivateCallback,
  480.                 (XtCallbackProc)pickSkillLevelCB, NULL );
  481.             XtAddCallback( button[1], XmNactivateCallback,
  482.                 (XtCallbackProc)autoSkillLevelCB, NULL );
  483.             XtAddCallback( button[3], XmNactivateCallback,
  484.                 (XtCallbackProc)helpCB, soloHelpFiles ) ;
  485.         }
  486.         else
  487.         {
  488.             XtAddCallback( button[0], XmNactivateCallback,
  489.                 (XtCallbackProc)restartTeamCB, resultsForm ) ;
  490.             XtAddCallback( button[3], XmNactivateCallback,
  491.                 (XtCallbackProc)helpCB, teamHelpFiles ) ;
  492.             XtUnmanageChild( button[1] ) ;
  493.         }
  494.         XtAddCallback( button[2], XmNactivateCallback,
  495.             (XtCallbackProc)exitCB, NULL ) ;
  496.  
  497.         n = 0 ;
  498.         XtSetArg( args[n], XmNmarginTop, 15 ) ; n++ ;
  499.         XtSetArg( args[n], XmNvisibleItemCount, 8 ) ; n++ ;
  500.         XtSetValues( resultsList, args, n ) ;
  501.     }
  502.  
  503.     XmListDeleteAllItems( resultsList ) ;
  504.  
  505.     placeCarsForFinish( position ) ;
  506.  
  507.     if( playMode == VROOM_SOLO || gameServerId == myHostId )
  508.     {
  509.         l = 1 ;
  510.     }
  511.     else
  512.     {
  513.         l = 0 ;
  514.     }
  515.     for( i = 0 ; i < MAX_PLAYERS ; i++ )
  516.     {
  517.         n = position[i] ;
  518.         if( i == 0 && checkRaceRecord( cars[n].finishTime,
  519.             cars[n].name, l ) )
  520.         {
  521.             sprintf( line, "%d - [%s] %s [New Record]", i + 1,
  522.                 longRaceTimeString( cars[n].finishTime, &l ),
  523.                 cars[n].name ) ;
  524.         }
  525.         else
  526.         {
  527.             sprintf( line, "%d - [%s] %s", i + 1,
  528.                 longRaceTimeString( cars[n].finishTime, &l ),
  529.                 cars[n].name ) ;
  530.         }
  531.         str = XmStringCreateLocalized( line ) ;
  532.         XmListAddItem( resultsList, str, 0 ) ;
  533.         XmStringFree( str ) ;
  534.     }
  535.  
  536.     XmListSelectPos( resultsList, player[self].place, True ) ;
  537. }
  538.  
  539.  
  540.  
  541. /*------------------------------------------------------------------------------
  542.  * Quick hack for debugging.
  543.  *----------------------------------------------------------------------------*/
  544. void
  545. endSoloGame(
  546.     void
  547.     )
  548. {
  549.     busyCursor() ;
  550.  
  551.     setWorkProc( VROOM_WP_SOLO, 0 ) ;
  552.  
  553.     XtUnmanageChild( localCourseForm ) ;
  554.  
  555.     controlMainWindow( 0 ) ;
  556.  
  557.     setIntroCarShot() ;
  558.  
  559.     createLocalCourseSelector( localCourseForm ) ;
  560.  
  561.     setAdminForm( localCourseForm ) ;
  562.  
  563.     controlIntroWindow( 1 ) ;
  564.  
  565.     unbusyCursor() ;
  566. }
  567.  
  568.  
  569.  
  570. /*------------------------------------------------------------------------------
  571.  * Preview a course.
  572.  *----------------------------------------------------------------------------*/
  573. void
  574. coursePreview(
  575.     char    *description,
  576.     Widget    courseForm
  577.     )
  578. {
  579.     int        n ;
  580.     Arg        args[20] ;
  581.     Widget        w ;
  582.     XmString    str ;
  583.     static int    init = 0 ;
  584.     static Widget    label ;
  585.  
  586.     busyCursor() ;
  587.  
  588.     setAdminForm( previewForm ) ;
  589.  
  590.     if( init == 0 )
  591.     {
  592.         init = 1 ;
  593.  
  594.         n = 0 ;
  595.         XtSetArg( args[n], XmNmarginTop, 5 ) ; n++ ;
  596.         XtSetArg( args[n], XmNmarginBottom, 5 ) ; n++ ;
  597.         XtSetArg( args[n], XmNtopAttachment, XmATTACH_NONE ) ; n++ ;
  598.         XtSetArg( args[n], XmNleftAttachment, XmATTACH_FORM ) ; n++ ;
  599.         XtSetArg( args[n], XmNrightAttachment, XmATTACH_FORM ) ; n++ ;
  600.         XtSetArg( args[n], XmNbottomAttachment, XmATTACH_FORM ) ; n++ ;
  601.         w = addMenuPushButton( previewForm, "Done", args, n,
  602.                     clearPreviewCB, courseForm ) ;
  603.  
  604.         n = 0 ;
  605.         XtSetArg( args[n], XmNmarginTop, 5 ) ; n++ ;
  606.         XtSetArg( args[n], XmNmarginBottom, 5 ) ; n++ ;
  607.         XtSetArg( args[n], XmNtopAttachment, XmATTACH_NONE ) ; n++ ;
  608.         XtSetArg( args[n], XmNleftAttachment, XmATTACH_FORM ) ; n++ ;
  609.         XtSetArg( args[n], XmNrightAttachment, XmATTACH_FORM ) ; n++ ;
  610.         XtSetArg( args[n], XmNbottomAttachment, XmATTACH_WIDGET ) ; n++;
  611.         XtSetArg( args[n], XmNbottomWidget, w ) ; n++ ;
  612.         label = XtCreateManagedWidget( "label", xmLabelWidgetClass,
  613.                         previewForm, args, n ) ;
  614.  
  615.         n = 0 ;
  616.         XtSetArg( args[n], XmNshadowType, XmSHADOW_IN ) ; n++ ;
  617.         XtSetArg( args[n], XmNshadowThickness, 2 ) ; n++ ;
  618.         XtSetArg( args[n], XmNtopAttachment, XmATTACH_FORM ) ; n++ ;
  619.         XtSetArg( args[n], XmNleftAttachment, XmATTACH_FORM ) ; n++ ;
  620.         XtSetArg( args[n], XmNrightAttachment, XmATTACH_FORM ) ; n++ ;
  621.         XtSetArg( args[n], XmNbottomAttachment, XmATTACH_WIDGET ) ; n++;
  622.         XtSetArg( args[n], XmNbottomWidget, label ) ; n++ ;
  623.         w = XtCreateManagedWidget( "frame", xmFrameWidgetClass,
  624.                         previewForm, args, n ) ;
  625.  
  626.         n = 0 ;
  627.         createPreviewOglWidget( w, args, n ) ;
  628.     }
  629.  
  630.     str = XmStringCreateLtoR( description, XmFONTLIST_DEFAULT_TAG ) ;
  631.     n = 0 ;
  632.     XtSetArg( args[n], XmNlabelString, str ) ; n++ ;
  633.     XtSetValues( label, args, n ) ;
  634.     XmStringFree( str ) ;
  635.  
  636.     unbusyCursor() ;
  637. }
  638.  
  639.  
  640.  
  641. /*------------------------------------------------------------------------------
  642.  * Clear the preview window and show the previous form.
  643.  *----------------------------------------------------------------------------*/
  644. static void
  645. clearPreviewCB(
  646.     Widget        w,
  647.     XtPointer    clientData,
  648.     XtPointer    callData
  649.     )
  650. {
  651.     busyCursor() ;
  652.  
  653.     setAdminForm( (Widget)clientData ) ;
  654.  
  655.     unbusyCursor() ;
  656. }
  657.  
  658.  
  659.  
  660. /*------------------------------------------------------------------------------
  661.  * Position the cars based on their total race time.
  662.  *----------------------------------------------------------------------------*/
  663. static void
  664. placeCarsForFinish(
  665.     char    position[]
  666.     )
  667. {
  668.     int    i ;
  669.     int    ibest ;
  670.     int    l ;
  671.     int    place = 0 ;
  672.     int    marker[MAX_PLAYERS] ;
  673.     float    bestTime ;
  674.  
  675.     for( i = 0 ; i < MAX_PLAYERS ; i++ )
  676.     {
  677.         marker[i] = 0 ;
  678.     }
  679.  
  680.     for( place = 0 ; place < MAX_PLAYERS ; place++ )
  681.     {
  682.         ibest = -1 ;
  683.         for( i = 0 ; i < MAX_PLAYERS ; i++ )
  684.         {
  685.             if( marker[i] == 0 && ( cars[i].finishTime < bestTime ||
  686.                 ibest == -1 ) )
  687.             {
  688.                 ibest = i ;
  689.                 bestTime = cars[i].finishTime ;
  690.             }
  691.         }
  692.         player[ibest].place = place + 1 ;
  693.         marker[ibest] = 1 ;
  694.     }
  695.  
  696.     for( i = 0 ; i < MAX_PLAYERS ; i++ )
  697.     {
  698.         position[player[i].place-1] = i ;
  699.     }
  700. }
  701.  
  702.  
  703.  
  704. /*------------------------------------------------------------------------------
  705.  * Create the name entry form callback.
  706.  *----------------------------------------------------------------------------*/
  707. static void
  708. enterNameCB(
  709.     Widget                w,
  710.     int                mode,
  711.     XmPushButtonCallbackStruct    *cbs
  712.     )
  713. {
  714.     int        n ;
  715.     Arg        args[20] ;
  716.     Widget        rc ;
  717.     Widget        label ;
  718.     Widget        tf ;
  719.     XmString    str ;
  720.     static char    *helpFiles[] = { "name.help", NULL } ;
  721.  
  722.     playMode = mode ;
  723.  
  724.     n = 0 ;
  725.     XtSetArg( args[n], XmNtopAttachment, XmATTACH_FORM ) ; n++ ;
  726.     XtSetArg( args[n], XmNleftAttachment, XmATTACH_FORM ) ; n++ ;
  727.     XtSetArg( args[n], XmNrightAttachment, XmATTACH_FORM ) ; n++ ;
  728.     XtSetArg( args[n], XmNbottomAttachment, XmATTACH_FORM ) ; n++ ;
  729.     XtSetArg( args[n], XmNentryAlignment, XmALIGNMENT_CENTER ) ; n++ ;
  730.     XtSetArg( args[n], XmNorientation, XmVERTICAL ) ; n++ ;
  731.     XtSetArg( args[n], XmNpacking, XmPACK_COLUMN ) ; n++ ;
  732.     XtSetArg( args[n], XmNadjustLast, True ) ; n++ ;
  733.     XtSetArg( args[n], XmNspacing, 10 ) ; n++ ;
  734.     XtSetArg( args[n], XmNmarginHeight, 10 ) ; n++ ;
  735.     XtSetArg( args[n], XmNmarginWidth, 10 ) ; n++ ;
  736.     rc = XtCreateManagedWidget( "rowColumn", xmRowColumnWidgetClass,
  737.                     nameForm, args, n ) ;
  738.  
  739.     n = 0 ;
  740.     str = XmStringCreateLocalized( "Enter your playing name:" ) ;
  741.     XtSetArg( args[n], XmNlabelString, str ) ; n++ ;
  742.     XtSetArg( args[n], XmNmarginTop, 5 ) ; n++ ;
  743.     XtSetArg( args[n], XmNmarginBottom, 5 ) ; n++ ;
  744.     XtCreateManagedWidget( "label", xmLabelWidgetClass, rc, args, n ) ;
  745.     XmStringFree( str ) ;
  746.  
  747.     n = 0 ;
  748.     XtSetArg( args[n], XmNmarginTop, 5 ) ; n++ ;
  749.     XtSetArg( args[n], XmNmarginBottom, 5 ) ; n++ ;
  750.     XtSetArg( args[n], XmNmaxLength, VROOM_NAMELEN - 1 ) ; n++ ;
  751.     tf = XtCreateManagedWidget( "textField", xmTextFieldWidgetClass,
  752.                 rc, args, n ) ;
  753.     XmTextFieldSetString( tf, myName ) ;
  754.     XmTextFieldSetSelection( tf, 0, strlen( myName ), CurrentTime ) ;
  755.     XmTextFieldSetInsertionPosition( tf, strlen( myName ) ) ;
  756.  
  757.     XtAddCallback( tf, XmNactivateCallback,
  758.             (XtCallbackProc)setNameCB, (XtPointer)tf ) ;
  759.  
  760.     n = 0 ;
  761.     addMenuPushButton( rc, "Ok", args, n, (XtCallbackProc)setNameCB,
  762.                 (XtPointer)tf ) ;
  763.  
  764.     n = 0 ;
  765.     XtSetArg( args[n], XmNorientation, XmHORIZONTAL ) ; n++ ;
  766.     XtCreateManagedWidget( "separator", xmSeparatorWidgetClass,
  767.                     rc, args, n ) ;
  768.  
  769.     n = 0 ;
  770.     addMenuPushButton( rc, "Help", args, n, helpCB, helpFiles ) ;
  771.     addMenuPushButton( rc, "Quit", args, n, exitCB, 0 ) ;
  772.  
  773.     setAdminForm( nameForm ) ;
  774. }
  775.  
  776.  
  777.  
  778. /*------------------------------------------------------------------------------
  779.  * Set the player's name.
  780.  *----------------------------------------------------------------------------*/
  781. static void
  782. setNameCB(
  783.     Widget        w,
  784.     Widget        textField,
  785.     XtPointer    callData
  786.     )
  787. {
  788.     char    *newName ;
  789.  
  790.     busyCursor() ;
  791.     newName = XmTextFieldGetString( textField ) ;
  792.     if( newName != NULL && strlen( newName ) > 0 )
  793.     {
  794.         myName = newName ;
  795.     }
  796.  
  797.     if( playMode == VROOM_SOLO )
  798.     {
  799.         pickSkillLevelCB( w, NULL, NULL ) ;
  800.     }
  801.     else
  802.     {
  803.         startTeamModeCB( w, NULL, NULL ) ;
  804.     }
  805. }
  806.  
  807.  
  808.  
  809. /*------------------------------------------------------------------------------
  810.  * Create a selection list.
  811.  *----------------------------------------------------------------------------*/
  812. void
  813. createSelectionList(
  814.     char    *title,
  815.     Widget    parent,
  816.     Widget    *list,
  817.     int    nButtons,
  818.     Widget    *button,
  819.     char    **labels,
  820.     Arg    pArgs[],
  821.     int    pN
  822.     )
  823. {
  824.     int        n ;
  825.     int        i ;
  826.     Arg        args[10] ;
  827.     XmString    str ;
  828.     Widget        row ;
  829.     Widget        label ;
  830.     Widget        form ;
  831.     Widget        form2 ;
  832.     Widget        separator ;
  833.  
  834.     form = XtCreateManagedWidget( "listForm", xmFormWidgetClass, parent,
  835.                     pArgs, pN ) ;
  836.  
  837.     n = 0 ;
  838.         XtSetArg( args[n], XmNtopAttachment, XmATTACH_NONE ) ; n++ ;
  839.         XtSetArg( args[n], XmNleftAttachment, XmATTACH_FORM ) ; n++ ;
  840.         XtSetArg( args[n], XmNrightAttachment, XmATTACH_FORM ) ; n++ ;
  841.         XtSetArg( args[n], XmNbottomAttachment, XmATTACH_FORM ) ; n++ ;
  842.         XtSetArg( args[n], XmNborderWidth, 0 ) ; n++ ;
  843.         XtSetArg( args[n], XmNspacing, 15 ) ; n++ ;
  844.     row = XtCreateManagedWidget( "row", xsRowWidgetClass,
  845.                     form, args, n ) ;
  846.  
  847.     n = 0 ;
  848.     XtSetArg( args[n], XmNmarginHeight, 5 ) ; n++ ;
  849.     XtSetArg( args[n], XmNmarginWidth, 5 ) ; n++ ;
  850.     for( i = 0 ; i < nButtons ; i++ )
  851.     {
  852.         button[i] = XtCreateManagedWidget( labels[i],
  853.                 xmPushButtonWidgetClass, row, args, n ) ;
  854.     }
  855.  
  856.     n = 0 ;
  857.         XtSetArg( args[n], XmNorientation, XmHORIZONTAL ) ; n++ ;
  858.         XtSetArg( args[n], XmNtopAttachment, XmATTACH_NONE ) ; n++ ;
  859.         XtSetArg( args[n], XmNleftAttachment, XmATTACH_FORM ) ; n++ ;
  860.         XtSetArg( args[n], XmNrightAttachment, XmATTACH_FORM ) ; n++ ;
  861.         XtSetArg( args[n], XmNbottomAttachment, XmATTACH_WIDGET ) ; n++ ;
  862.         XtSetArg( args[n], XmNbottomWidget, row ) ; n++ ;
  863.     separator = XtCreateManagedWidget( "separator", xmSeparatorWidgetClass,
  864.                         form, args, n ) ;
  865.  
  866.     n = 0 ;
  867.         XtSetArg( args[n], XmNtopAttachment, XmATTACH_FORM ) ; n++ ;
  868.         XtSetArg( args[n], XmNleftAttachment, XmATTACH_FORM ) ; n++ ;
  869.         XtSetArg( args[n], XmNrightAttachment, XmATTACH_FORM ) ; n++ ;
  870.         XtSetArg( args[n], XmNbottomAttachment, XmATTACH_WIDGET ) ; n++ ;
  871.         XtSetArg( args[n], XmNbottomWidget, separator ) ; n++ ;
  872.     XtSetArg( args[n], XmNhorizontalSpacing, 14 ) ; n++ ;
  873.     XtSetArg( args[n], XmNverticalSpacing, 10 ) ; n++ ;
  874.     form2 = XtCreateManagedWidget( "listForm2", xmFormWidgetClass, form,
  875.                     args, n ) ;
  876.  
  877.     str = XmStringCreateLocalized( title ) ;
  878.     n = 0 ;
  879.         XtSetArg( args[n], XmNlabelString, str ) ; n++ ;
  880.         XtSetArg( args[n], XmNmarginTop, 15 ) ; n++ ;
  881.         XtSetArg( args[n], XmNtopAttachment, XmATTACH_FORM ) ; n++ ;
  882.         XtSetArg( args[n], XmNleftAttachment, XmATTACH_FORM ) ; n++ ;
  883.         XtSetArg( args[n], XmNrightAttachment, XmATTACH_FORM ) ; n++ ;
  884.         XtSetArg( args[n], XmNbottomAttachment, XmATTACH_NONE ) ; n++ ;
  885.     label = XtCreateManagedWidget( "label", xmLabelWidgetClass, form2,
  886.                     args, n ) ;
  887.     XmStringFree( str ) ;
  888.  
  889.     n = 0 ;
  890.         XtSetArg( args[n], XmNtopAttachment, XmATTACH_WIDGET ) ; n++ ;
  891.         XtSetArg( args[n], XmNtopWidget, label ) ; n++ ;
  892.         XtSetArg( args[n], XmNleftAttachment, XmATTACH_FORM ) ; n++ ;
  893.         XtSetArg( args[n], XmNrightAttachment, XmATTACH_FORM ) ; n++ ;
  894.         XtSetArg( args[n], XmNbottomAttachment, XmATTACH_FORM ) ; n++ ;
  895.         XtSetArg( args[n], XmNvisibleItemCount, 5 ) ; n++ ;
  896.         XtSetArg( args[n], XmNscrollBarDisplayPolicy, XmSTATIC ) ; n++ ;
  897.     *list = XmCreateScrolledList( form2, "list", args, n ) ;
  898.     XtManageChild( *list ) ;
  899. }
  900.